package com.example.authsystem.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "roles")
@Schema(
        name = "Role",
        description = "角色实体类，定义系统中的用户角色和权限体系。",
        example = """
                {
                  "id": 1,
                  "name": "ADMIN",
                  "description": "系统管理员，拥有所有权限",
                  "permissions": [
                    "USER_READ",
                    "USER_WRITE",
                    "USER_DELETE",
                    "ROLE_MANAGE",
                    "SYSTEM_CONFIG"
                  ]
                }
                """
)
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Schema(
            description = """
                    角色唯一标识符，系统自动生成。
                                
                    特性：
                    - 主键，自动递增
                    - 不可修改
                    - 用于角色关联和引用
                    - 数据库中唯一
                    """,
            example = "1",
            accessMode = Schema.AccessMode.READ_ONLY,
            minimum = "1"
    )
    @JsonProperty("id")
    private Long id;

    @Column(unique = true, nullable = false)
    @Schema(
            description = "角色名称，系统内唯一标识。",
            example = "ADMIN",
            requiredMode = Schema.RequiredMode.REQUIRED,
            minLength = 2,
            maxLength = 50,
            pattern = "^[A-Z][A-Z0-9_]*$"
    )
    @NotBlank(message = "角色名称不能为空")
    @Size(min = 2, max = 50, message = "角色名称长度必须在2-50个字符之间")
    @JsonProperty("name")
    private String name;

    @Schema(
            description = "角色描述信息，详细说明角色的用途和职责。",
            example = "系统管理员，拥有所有系统权限，负责用户管理、系统配置和数据维护",
            maxLength = 500
    )
    @Size(max = 500, message = "角色描述不能超过500个字符")
    @JsonProperty("description")
    private String description;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "role_permissions", joinColumns = @JoinColumn(name = "role_id"))
    @Column(name = "permission")
    @Schema(
            description = "角色包含的权限列表，定义该角色可以执行的操作。",
            example = """
                    [
                      "USER_READ",
                      "USER_WRITE", 
                      "USER_DELETE",
                      "ROLE_MANAGE",
                      "SYSTEM_CONFIG",
                      "AUDIT_LOG_READ"
                    ]
                    """,
            type = "array"
    )
    @JsonProperty("permissions")
    private List<String> permissions = new ArrayList<>();

    // Constructors

    /**
     * 默认构造函数
     */
    public Role() {
    }

    /**
     * 基础构造函数
     *
     * @param name        角色名称
     * @param description 角色描述
     */
    public Role(String name, String description) {
        this.name = name;
        this.description = description;
        this.permissions = new ArrayList<>();
    }

    /**
     * 完整构造函数
     *
     * @param name        角色名称
     * @param description 角色描述
     * @param permissions 权限列表
     */
    public Role(String name, String description, List<String> permissions) {
        this.name = name;
        this.description = description;
        this.permissions = permissions != null ? new ArrayList<>(permissions) : new ArrayList<>();
    }

    // Getters and Setters

    /**
     * 获取角色ID
     *
     * @return 角色ID
     */
    public Long getId() {
        return id;
    }

    /**
     * 设置角色ID
     *
     * @param id 角色ID
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * 获取角色名称
     *
     * @return 角色名称
     */
    public String getName() {
        return name;
    }

    /**
     * 设置角色名称
     *
     * @param name 角色名称
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取角色描述
     *
     * @return 角色描述
     */
    public String getDescription() {
        return description;
    }

    /**
     * 设置角色描述
     *
     * @param description 角色描述
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * 获取权限列表
     *
     * @return 权限列表
     */
    public List<String> getPermissions() {
        return permissions;
    }

    /**
     * 设置权限列表
     *
     * @param permissions 权限列表
     */
    public void setPermissions(List<String> permissions) {
        this.permissions = permissions != null ? new ArrayList<>(permissions) : new ArrayList<>();
    }

    // 业务方法

    /**
     * 添加权限
     *
     * @param permission 权限名称
     * @return 是否添加成功
     */
    @Schema(hidden = true)  // 隐藏业务方法，不在API文档中显示
    public boolean addPermission(String permission) {
        if (permission != null && !permission.trim().isEmpty() && !this.permissions.contains(permission)) {
            return this.permissions.add(permission);
        }
        return false;
    }

    /**
     * 移除权限
     *
     * @param permission 权限名称
     * @return 是否移除成功
     */
    @Schema(hidden = true)
    public boolean removePermission(String permission) {
        return this.permissions.remove(permission);
    }

    /**
     * 检查是否拥有指定权限
     *
     * @param permission 权限名称
     * @return 是否拥有权限
     */
    @Schema(hidden = true)
    public boolean hasPermission(String permission) {
        return this.permissions.contains(permission);
    }

    /**
     * 清空所有权限
     */
    @Schema(hidden = true)
    public void clearPermissions() {
        this.permissions.clear();
    }

    /**
     * 获取权限数量
     *
     * @return 权限数量
     */
    @Schema(hidden = true)
    public int getPermissionCount() {
        return this.permissions.size();
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", permissionCount=" + (permissions != null ? permissions.size() : 0) +
                '}';
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;

        Role role = (Role) obj;

        if (id != null ? !id.equals(role.id) : role.id != null) return false;
        return name != null ? name.equals(role.name) : role.name == null;
    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}